package com.yuqih.common.event;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;

public class DefaultRefreshEventDispatcher implements IRefreshEventDispatcher, IRefreshEventListenerRegistry {
	
	private final List<IRefreshEventListener<?>> modelEventListeners = new ArrayList<IRefreshEventListener<?>>();
	private ExecutorService executorService;
	private final Dispatcher dispatcher = new Dispatcher();
	
	private BlockingQueue<RefreshEvent<?>> queue = new LinkedBlockingDeque<RefreshEvent<?>>();
	
	public void init() {
		executorService.execute(dispatcher);
	}
	
	public void destroy() {
		dispatcher.state = false;
	}
	
	@Override
	public void dispatch(RefreshEvent<?> event) {
		queue.add(event);
	}

	@Override
	public void register(IRefreshEventListener<?> listener) {
		synchronized (modelEventListeners) {
			modelEventListeners.add(listener);
		}
	}

	/**
	 * @param executorService the executorService to set
	 */
	public void setExecutorService(ExecutorService executorService) {
		this.executorService = executorService;
	}
	
	private class Dispatcher implements Runnable {
		
		private boolean state = true;

		@SuppressWarnings("rawtypes")
		@Override
		public void run() {
			while (state) {
				try {
					RefreshEvent<?> event = queue.take();
					synchronized (modelEventListeners) {
						for (IRefreshEventListener listener : modelEventListeners) {
							if (!Objects.equals(event.getType(), listener.type())){
								continue;
							}
							executorService.execute(new Runnable() {
								
								@SuppressWarnings("unchecked")
								@Override
								public void run() {
									listener.listen(event);
								}
							});
						}
					}
					
				} catch (InterruptedException e) {
					continue;
				}
			}
			
		}
		
	}
	
}
